from smbus import SMBus


class RadioStatus:
    RADIO_PLAY = 0
    RADIO_SEARCHING_UP = 1
    RADIO_SEARCHING_DOWN = 2
    RADIO_PAUSE = 3

    BAD_FREQUENCY = -1


class Tea5767:

    UPPER_BAND_LIMIT = 108
    LOWER_BAND_LIMIT = 87.5
    BAND_STEP = 0.1

    def __init__(self):
        # i2c
        self.__i2c = SMBus(1)
        self.__address = 0x60
        self.__crystalOscillatorFrequency = 32768
        self.__dataSize = 5

        # radio parameter
        self.mute = 0
        # just for logistic usage, not chip mode
        # self.searchMode = 0
        self.frequency = Tea5767.LOWER_BAND_LIMIT

    def __encode14bits_frequency(self, frequency):
        frequency14bits = int(4 * (frequency * 1000000+225000) / self.__crystalOscillatorFrequency)
        return [int(frequency14bits >> 8), int(frequency14bits & 0xff)]

    def __decode14bit_frequency(self, upper, lower):
        # return round((float(round(int(((int(upper) << 8)+int(lower)) * self.__crystalOscillatorFrequency / 4 - 22500) / 100000) / 10) - .2) * 10) / 10
        frequency14bits = int(int(upper << 8) + int(lower))
        frequency = round(frequency14bits * self.__crystalOscillatorFrequency / 4 - 225000) / 1000000
        return round(frequency, 1)

    def __construct_i2c_data(self, reading=False):
        data = [0x00, 0x00, 0b00110000, 0b00010000, 0x00]
        upperBits, lowerBits = self.__encode14bits_frequency(self.frequency)
        if self.mute == 1:
            data[0] += 0b10000000

        data[0] += upperBits
        if not reading:
            data[1] += lowerBits

        return data

    def __parse_i2c_data(self, data):
        ready = 1 if data[0] & 0b10000000 else 0
        limit = 1 if data[0] & 0b01000000 else 0
        upperBits = data[0] & 0b00111111
        lowerBits = data[1]
        frequency = self.__decode14bit_frequency(upperBits, lowerBits)
        level = data[3] >> 4
        return limit, ready, frequency, level

    def __write_i2c_data(self, data):
        self.__i2c.write_i2c_block_data(self.__address, data[0], data[1:])

    def __read_i2c_data(self):
        data = self.__construct_i2c_data(reading=True)
        return self.__i2c.read_i2c_block_data(self.__address, data[0], self.__dataSize)

    def __write_frequency(self, frequency, quiet=False):
        self.frequency = frequency
        self.mute = 1 if quiet else 0
        self.__write_i2c_data(self.__construct_i2c_data())

    def __read_frequency(self):
        return self.__parse_i2c_data(self.__read_i2c_data())

    def set_mute(self, muted):
        self.__write_frequency(self.frequency, quiet=muted)

    def set_frequency(self, frequency, quiet=False):
        """
        :param frequency: valid range of [87.5, 108]
        :param quiet: muted while set frequency
        """

        if frequency < Tea5767.LOWER_BAND_LIMIT or frequency > Tea5767.UPPER_BAND_LIMIT:
            return RadioStatus.BAD_FREQUENCY
        self.__write_frequency(frequency, quiet)

    def search_query(self):
        """:returns [limit, ready, frequency, signal]"""

        return self.__read_frequency()

    def get_frequency(self):
        """:return [frequency, signal]"""

        return self.__read_frequency()[2:]


if __name__ == "__main__":
    radio = Tea5767()
    radio.set_frequency(90.5)
    print(radio.search_query())